home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 001a / cscom.zip / CSCOM.8 next >
Text File  |  1991-10-09  |  31KB  |  1,502 lines

  1. ;CSCOM is a modem communication program for calling CompuServe and
  2. ;downloading a file using CompuServe's B+ protocol with an IBM
  3. ;compatible computer.  I'm releasing CSCOM.COM and CSCOM.8 (the
  4. ;8086 assembly language source code file) to the Public Domain.
  5.  
  6. ;It isn't as complete as it could be, but it's free.  Feel free
  7. ;to improve on it.
  8.  
  9. ;The weak areas are in the B+ protocol downloading routines.  My
  10. ;source of information for the B+ protocol was BPLUS.DOC, which was
  11. ;the original documentation for the protocol, by Russ Ranshaw. It's a
  12. ;very impressive document, but it's ambiguous/vague/incomplete in
  13. ;some areas.  I learned a lot by trial and error, but I didn't learn
  14. ;everything I wanted to.  And my knowledge of Pascal didn't help much
  15. ;with the source code by Russ Ranshaw called BPLUS.PAS.
  16.  
  17. ;o  You can't exit the program while the download is in progress.
  18. ;o  You can only download, not upload.
  19. ;o  I'm not sure all possible errors are covered.
  20. ;o  The download might be made to go a little faster.
  21. ;o  The file to be downloaded must fit in memory beginning 64K above CSCOM.
  22.  
  23. ;CSCOM was written using the ShareWare assembler, A86, which I highly
  24. ;recommend, in Oct, 1991.
  25.  
  26. ;Doug Cox
  27. ;140 Monroe Dr.
  28. ;Palo Alto, Ca. 94306
  29. ;(415) 949-0624
  30. ;CompuServe ID# 70224,22
  31.  
  32.   JMP MAIN
  33. SCREENSEG DW ?        ;SCREEN SEGMENT
  34. NEXTSEG DW ?        ;TO HOLD NEXT SEGMENT ADDRESS
  35. ATTRIB DB 7        ;SCREEN COLOR ATTRIBUTE
  36. BOXATTRIB DB 017
  37. CURATTRIB DB 067
  38. CFG DB 'CSCOM.CFG',0    ;HOLDS PHONE NUM, USER ID, & PASSWORD
  39. HANDLE DW ?
  40. CURLINELOC DW 361
  41. CUROW DB 25,3,4,5,6,7    ;CURSOR ROWS
  42. CUROWPTR DW OFFSET CUROW
  43. ROWCOL LABEL WORD
  44. COL DB 0
  45. ROW DB 0
  46. HUNDRED DW 100
  47. TEMPSTORAGE DW ?
  48. FLAGBYTE DB ?           ;USED AS A FLAG AND FOR INT 015
  49. CALLMENU:
  50.   DB '┌────────────Call CompuServe─────────────┐'
  51.   DB '│ Move cursor here & press Enter to call │'
  52.   DB '│    Phone Number: *70-415-949-0624      │'
  53.   DB '│    User ID:      70224,22              │'
  54.   DB '│    Password:                           │'
  55.   DB '│    Modem Speed:  2400                  │'
  56.   DB '│    Comm Port:    1                     │'
  57.   DB '└───────────Press ESC to Exit────────────┘'
  58. COMPORT DB '1'
  59. INIT DB 'ATE1Q0V1X4&C1&D2',0D,0 ;INITIALIZE MODEM
  60.   DW 3            ;LENGTH OF FOLLOWING STRING
  61. OK DB 'OK',0D,0
  62. CALLING DB 'Calling CompuServe$'
  63. PHONENO DB 'ATDT'
  64. PHONE2 DB 22 DUP('1')
  65.   DW 12
  66. CONNECT DB 'CONNECT '
  67. SPEED DB '2400'
  68. SENDCR DB 0D,0            
  69.  DW 11
  70. HOST DB 'Host Name: '
  71. SENDHOST DB 'CIS',0D,0
  72.  DW 9
  73. USER DB 'User ID: '
  74. SENDUSER DB 22 DUP('0')
  75.  DW 10
  76. PASSWORD DB 'Password: '
  77. SENDPASS DB 22 DUP('X')
  78.  DW 1
  79. EXCLAIM DB '!'
  80.  
  81. TR_BUFFER DW ?        ;UART PORT ADDRESS
  82. INT_ENABLE DW ?     ;+1
  83. INT_IDENT DW ?        ;+2
  84. LINE_CONTROL DW ?    ;+3
  85. MODEM_CONTROL DW ?    ;+4
  86. LINE_STATUS DW ?    ;+5
  87. MODEM_STATUS DW ?    ;+6
  88. COMM_INT_STA DB ?    ;COMMUNICATIONS INTERRUPT STATUS
  89.  
  90. INTOFF DW ?        ;TO HOLD DEFAULT COMM INTERRUPT VECTOR
  91. INTSEG DW ?
  92.  
  93. IN_BUFF_HEAD DW ?
  94. IN_BUFF_TAIL DW ?
  95. IN_BUFF_BEGIN DW ?
  96. IN_BUFF_END DW ?
  97. OUT_BUFF_HEAD DW ?
  98. OUT_BUFF_TAIL DW ?
  99. OUT_BUFF_BEGIN DW ?
  100. OUT_BUFF_END DW ?
  101.  
  102. MAIN:
  103.   MOV AX,03D02        ;FUNCTION TO OPEN FILE FOR READ/WRITE
  104.   MOV DX,OFFSET CFG
  105.   INT 021
  106.   JNC GOTFILE           ;IF FILE OPENED
  107.   MOV FLAGBYTE,0    ;NO .CFG FILE
  108.   JMP SHORT NOFILE
  109. GOTFILE:
  110.   MOV FLAGBYTE,1    ;IF .CFG FILE EXISTS
  111.   MOV HANDLE,AX
  112.   MOV BX,AX
  113.   MOV AH,03F        ;FUNCTION TO READ FILE
  114.   MOV CX,110        ;NUMBER OF BYTES
  115.   MOV DX,OFFSET BUF    ;WHERE TO PUT FILE
  116.   INT 021
  117.   MOV AX,04200        ;FUNCTION TO MOVE FILE POINTER TO BEGINNING OF FILE
  118.   SUB CX,CX
  119.   SUB DX,DX
  120.   INT 021
  121.   MOV SI,OFFSET BUF
  122.   MOV DX,OFFSET CALLMENU
  123.   ADD DX,61
  124.   MOV BX,5
  125. L0:
  126.   ADD DX,42
  127.   MOV DI,DX
  128.   MOV CX,22
  129.   REP MOVSB
  130.   DEC BX
  131.   JNZ L0
  132.   CALL BUF2MEM        ;MOV BUF DATA TO PHONE2, ETC
  133. NOFILE:
  134.   MOV AH,0F        ;FUNCTION TO GET CURRENT DISPLAY MODE
  135.   INT 010
  136.   MOV SCREENSEG,0B800
  137.   CMP AL,7
  138.   JNE >L1        ;IF NOT MONO MODE
  139.   MOV SCREENSEG,0B000
  140.   MOV BOXATTRIB,7
  141.   MOV CURATTRIB,070
  142. L1:
  143.   MOV AX,CS
  144.   ADD AX,01000
  145.   MOV NEXTSEG,AX    ;FOR DOWNLOADED DATA
  146. DRAWBOX:
  147.   CALL CLRSCRN
  148.   MOV ES,SCREENSEG
  149.   MOV SI,OFFSET CALLMENU
  150.   MOV AL,BOXATTRIB
  151.   MOV DX,198        ;SCREEN OFFSET
  152.   MOV BX,8        ;ROWS
  153. L1:
  154.   MOV DI,DX
  155.   MOV CX,42        ;COLS
  156. L2:
  157.   MOVSB
  158.   STOSB
  159.   LOOP L2
  160.   ADD DX,160
  161.   DEC BX
  162.   JNZ L1
  163. PREADKBD:
  164.   CALL MAKECURLINE
  165.   MOV BX,CUROWPTR
  166.   MOV AL,[BX]
  167.   MOV ROW,AL
  168.   MOV COL,38        ;BEGINNING OF INPUT
  169. PREAD2:
  170.   CALL MOVCUR
  171. READKBD:
  172.   MOV AH,0
  173.   INT 016
  174.   CMP AX,05000        ;DOWN ARROW
  175.   JNE >L1
  176. GODOWN:
  177.   CMP CURLINELOC,1161
  178.   JE READKBD        ;IF AT BOTTOM
  179.   MOV AL,BOXATTRIB
  180.   CALL CURLINE        ;CLEAR CURSOR LINE
  181.   ADD CURLINELOC,160
  182.   INC CUROWPTR
  183.   JMP PREADKBD
  184. L1:
  185.   CMP AX,04800        ;UP ARROW
  186.   JNE >L2
  187.   CMP CURLINELOC,361
  188.   JE READKBD        ;IF AT TOP
  189.   MOV AL,BOXATTRIB
  190.   CALL CURLINE
  191.   SUB CURLINELOC,160
  192.   DEC CUROWPTR
  193.   JMP PREADKBD
  194. L2:
  195.   CMP AX,04B00        ;LEFT ARROW
  196.   JNE >L3
  197.   CMP COL,38
  198.   JE READKBD
  199.   DEC COL
  200.   JMP SHORT PREAD2
  201. L3:
  202.   CMP AX,04D00        ;RIGHT ARROW
  203.   JNE >L4
  204.   CMP COL,59
  205.   JE READKBD
  206.   INC COL
  207.   JMP SHORT PREAD2
  208. L4:
  209.   CMP AL,0D        ;ENTER
  210.   JNE >L5
  211.   CMP CURLINELOC,1161
  212.   JNE L45        ;IF NOT AT BOTTOM LINE
  213.   MOV W[ROWCOL],0326    ;TOP LINE
  214.   MOV AL,BOXATTRIB
  215.   CALL CURLINE        ;CLEAR CURSOR LINE
  216.   MOV CURLINELOC,361    ;TOP LINE
  217.   MOV CUROWPTR,OFFSET CUROW
  218.   JMP PREADKBD
  219. L45:
  220.   CMP CURLINELOC,361
  221.   JE MODEM        ;IF AT TOP LINE
  222.   JMP GODOWN
  223. L5:
  224.   CMP AL,01B        ;ESC
  225.   IF E JMP EXIT
  226. L6:
  227.   CMP AX,02D00        ;ALT-X
  228.   IF E JMP EXIT
  229. L7:
  230.   CMP AL,8        ;BACKSPACE
  231.   JNE >L8
  232.   CMP COL,38
  233.   JE JMPREADKBD
  234.   DEC COL
  235.   CALL MOVCUR
  236.   MOV AL,' '
  237.   CALL WRITIT
  238.   JMP READKBD
  239. L8:
  240.   CMP AX,05300        ;DELETE
  241.   JNE >L9
  242.   MOV AL,' '
  243.   CALL WRITIT
  244. JMPREADKBD:
  245.   JMP READKBD
  246. L9:
  247.   CMP AL,' '
  248.   JB JMPREADKBD
  249.   CMP AL,07F
  250.   JA JMPREADKBD
  251.   CMP AL,'a'
  252.   JB >L0
  253.   CMP AL,'z'
  254.   JA >L0
  255.   AND AL,0DF        ;MAKE IT UPPERCASE
  256. L0:
  257.   CALL WRITIT
  258.   CMP COL,59
  259.   JE JMPREADKBD
  260.   INC COL
  261.   JMP PREAD2
  262.  
  263. MODEM:
  264.   MOV AX,DS
  265.   MOV ES,AX
  266.   MOV DS,SCREENSEG    ;!
  267.   MOV DI,BUF
  268.   MOV DX,396
  269.   MOV BX,5
  270. L1:
  271.   ADD DX,160
  272.   MOV SI,DX
  273.   MOV CX,22
  274. L2:
  275.   MOVSB
  276.   INC SI
  277.   LOOP L2
  278.   DEC BX
  279.   JNZ L1
  280.   MOV AX,CS
  281.   MOV DS,AX
  282.   CALL BUF2MEM        ;MOV BUF DATA TO PHONE2, ETC
  283.   CMP FLAGBYTE,0
  284.   JNZ >L3        ;IF .CFG FILE EXISTS
  285.   MOV AH,03C            ;FUNCTION TO CREATE/TRUNCATE FILE
  286.   MOV CX,0              ;FILE ATTRIB
  287.   MOV DX,OFFSET CFG
  288.   INT 021
  289.   MOV HANDLE,AX
  290. L3:
  291.   MOV AH,040            ;FUNCTION TO WRITE FILE
  292.   MOV BX,HANDLE
  293.   MOV CX,110        ;NUMBER OF BYTES TO WRITE
  294.   MOV DX,OFFSET BUF
  295.   INT 021
  296.  
  297. ;INITIALIZE UART PORT ADDRESSES
  298.   MOV AL,COMPORT
  299.   SUB AL,'1'
  300.   CBW
  301.   SHL AX,1        ;MUL 2
  302.   MOV SI,AX
  303.   MOV AX,040        ;SEGMENT WHERE COM PORT ADDRESS IS
  304.   MOV DS,AX        ;!
  305.   MOV AX,[SI]
  306.   MOV CX,CS
  307.   MOV DS,CX
  308.   OR AX,AX
  309.   JNZ GOTPORT        ;IF THERE'S AN ADDRESS THERE
  310.   JMP EXIT
  311. GOTPORT:
  312.   MOV DI,OFFSET TR_BUFFER
  313.   MOV CX,7
  314. L1:
  315.   STOSW         ;INITIALIZE PORT ADDRESSES
  316.   INC AX        ;NEXT ADDRESS
  317.   LOOP L1
  318.  
  319.   MOV AH,0        ;FUNCTION TO CONFIGURE COMM PORT
  320. ;  MOV AL,00011010xB     ;EVEN PARITY, 1 STOP BIT, 7 BITS
  321.   MOV AL,3        ;NO PARITY, 1 STOP BIT, 8 BITS
  322.   MOV BL,10100000xB    ;FOR 2400 BAUD
  323.   MOV SI,OFFSET SPEED
  324.   CMP W[SI],'3 '
  325.   JNE >L2
  326.   MOV BL,01000000xB
  327.   JMP SHORT >L5
  328. L2:
  329.   CMP W[SI],'30'
  330.   JNE >L3
  331.   MOV BL,01000000xB
  332.   JMP SHORT >L5
  333. L3:
  334.   CMP W[SI],'21'
  335.   JNE >L4
  336.   MOV BL,10000000xB
  337.   JMP SHORT >L5
  338. L4:
  339.   CMP W[SI],'69'
  340.   JNE >L5
  341.   MOV BL,11100000xB
  342. L5:
  343.   OR AL,BL        ;MODEM SPEED
  344.   MOV DL,B[COMPORT]
  345.   SUB DL,'1'
  346.   MOV DH,0
  347.   INT 014        ;BIOS CONFIGURES COMM PORT
  348.  
  349.   MOV DX,INT_IDENT
  350. ;  MOV AL,11000001xB     ;ENABLE 16550A BUFFER
  351.   MOV AL,0        ;DISABLE 16550A BUFFER
  352.   OUT DX,AL        
  353.  
  354. ;INITIALIZE BUFFERS
  355.   MOV CX,OFFSET IN_BUFF
  356.   MOV BX,OFFSET IN_BUFF_HEAD
  357.   MOV W[BX],CX
  358.   MOV W[BX+2],CX    ;IN_BUFF_TAIL
  359.   MOV W[BX+4],CX    ;IN_BUFF_BEGIN
  360.   ADD CX,IN_BUFF_SIZE    ;8080
  361.   MOV W[BX+6],CX    ;IN_BUFF_END
  362.   MOV BX,OFFSET OUT_BUFF_HEAD
  363.   MOV W[BX],CX
  364.   MOV W[BX+2],CX
  365.   MOV W[BX+4],CX
  366.   ADD CX,OUT_BUFF_SIZE
  367.   MOV W[BX+6],CX
  368.  
  369. ;ENABLE INTS, MODIFY THE INTERRUPT VECTOR FOR THE COMM PORT, AND SET 8259 MASK
  370.   CLI
  371.   MOV DX,MODEM_CONTROL
  372.   MOV AL,00001011xB
  373.   OUT DX,AL        ;TURN ON DTR, RTS, & ENABLE INTERRUPTS
  374.   STI
  375.   CMP B[COMPORT],'1'
  376.   JE >L1
  377.   MOV AL,11        ;INT VECTOR FOR COMM2
  378.   MOV BL,11110111xB    ;MASK FOR 8259 COMM2
  379.   JMP SHORT >L2
  380. L1:
  381.   MOV AL,12        ;INT VECTOR FOR COMM1
  382.   MOV BL,11101111xB    ;MASK FOR 8259 COMM1
  383. L2:
  384.   PUSH AX,BX        ;SAVE AL
  385.   MOV AH,035        ;FUCTION TO GET INTERRUPT VECTOR
  386.   INT 021
  387.   MOV INTOFF,BX
  388.   MOV INTSEG,ES
  389.   MOV AX,CS
  390.   MOV ES,AX
  391.   POP BX,AX        ;GET AL & MASK
  392.   MOV AH,025        ;FUNCTION FOR COMM INT VECTOR TO POINT TO INT_COMM
  393.   MOV DX,OFFSET INT_COMM;COMM INTERRUPT ROUTINE
  394.   INT 021
  395.   IN AL,021        ;GET CURRENT 8259 INT MASK
  396.   AND AL,BL        ;MASK APPROPRIATE BIT
  397.   OUT 021,AL        ;NEW 8259 MASK
  398. ;ENABLE DATA RECEIVED INTERRUPT AND RESET 8250
  399.   MOV DX,INT_ENABLE
  400.   MOV AL,00000011xB    ;ENABLE DATA RECEIVED & THR EMPTY INTERRUPTS
  401.   OUT DX,AL
  402.  
  403.   MOV DX,TR_BUFFER    ;aka THR
  404.   MOV CX,7
  405. L3:
  406.   IN AL,DX        ;READ UART REGISTERS TO RESET THEM
  407.   INC DX
  408.   LOOP L3
  409.   MOV AX,OUT_BUFF_TAIL
  410.   MOV OUT_BUFF_HEAD,AX
  411.   MOV AX,IN_BUFF_TAIL
  412.   MOV IN_BUFF_HEAD,AX
  413.  
  414. ;CALL COMPUSERVE...
  415.   MOV SI,OFFSET INIT
  416.   CALL LOAD_STRING    ;INITIALIZE MODEM
  417.   MOV BX,OFFSET OK
  418.   CALL WAITFOR2
  419.   MOV ROWCOL,0A00
  420.   CALL MOVCUR
  421.   MOV AH,9
  422.   MOV DX,OFFSET CALLING
  423.   INT 021
  424.   CALL DELAY
  425.   MOV SI,OFFSET PHONENO ;CALL COMPUSERVE
  426.   CALL LOAD_STRING
  427.   MOV AH,1
  428.   INT 016
  429.   JZ >L1        ;IF NO KEY PRESSED
  430.   MOV AH,0        ;CLEAR KEYBOARD BUFFER
  431.   INT 016
  432.   JMP MAIN
  433. L1:
  434.   MOV BX,OFFSET CONNECT
  435.   CALL WAITFOR2
  436.   CALL DELAY
  437.   MOV SI,OFFSET SENDCR
  438.   CALL TRANSMIT
  439.   MOV BX,OFFSET HOST
  440.   CALL WAITFOR
  441.   MOV SI,OFFSET SENDHOST
  442.   CALL TRANSMIT
  443.   MOV BX,OFFSET USER
  444.   CALL WAITFOR
  445.   MOV SI,OFFSET SENDUSER
  446.   CALL TRANSMIT
  447.   MOV BX,OFFSET PASSWORD
  448.   CALL WAITFOR
  449.   MOV SI,OFFSET SENDPASS
  450.   CALL TRANSMIT
  451. DOWNLOADRET:
  452.   MOV BX,OFFSET EXCLAIM
  453.   CALL WAITFOR
  454.  
  455. PREKEYINPUT:
  456.   MOV DI,BUF
  457. KEYINPUT:
  458.   MOV AH,1        ;FUNCTION TO GET KEYBOARD STATUS
  459.   INT 016
  460.   JNZ CHKBD        ;IF KEYBOARD INPUT
  461.   CALL GET_BUFF_DATA2
  462.   JNC KEYINPUT        ;IF NOTHING IN BUFFER
  463.   CMP AL,ENQ
  464.   IF E JMP DOWNLOAD
  465.   AND AL,07F        ;STRIP HI BIT (I THINK COMPUSERVE ALWAYS SENDS PARITY)
  466.   STOSB         ;ADD IT TO STRING IN BUF
  467.   CALL WRITE        ;WRITE CHAR ON SCREEN
  468.   JMP SHORT KEYINPUT
  469. CHKBD:
  470.   MOV AH,0        ;FUNCTION TO GET KEYBOARD CHAR
  471.   INT 016
  472. GOMANUAL:
  473.   CMP AL,0
  474.   JZ EXTENDEDKEY    ;IF NOT NORMAL CHAR
  475.   CMP AL,01B        ;ESC
  476.   JE EXIT_MANNED
  477.   CALL PUT_BUFF_DATA
  478.   JMP SHORT KEYINPUT
  479. EXTENDEDKEY:
  480.   CMP AH,02D        ;ALT-X
  481.   JNE KEYINPUT
  482.  
  483. ;Disable the serial port interrupts and reset the 8259 mask
  484. EXIT_MANNED:
  485.   MOV DX,INT_ENABLE    ;Interrupt enable reg.
  486.   MOV AL,0
  487.   OUT DX,AL        ;Disable all interrupts
  488.   CMP B[COMPORT],'1'    ;Determine mask bit to change
  489.   JZ EM_10
  490.   MOV BL,00001000xB    ;Mask for 8259 comm2
  491.   JMP SHORT EM_20
  492. EM_10:
  493.   MOV BL,00010000xB    ;Mask for 8259 comm1
  494. EM_20:
  495.   IN AL,021        ;Get current 8259 int mask
  496.   OR AL,BL        ;Set appropriate int bit
  497.   OUT 021,AL        ;And set new 8259 mask
  498.   MOV AL,11        ;Vector for comm2
  499.   CMP B[COMPORT],'1'    ;Determine INT vector to change
  500.   IF E MOV AL,12    ;Vector for comm1
  501.   MOV AH,025        ;FUNCTION TO SET INTERRUPT VECTOR
  502.   MOV DX,INTOFF
  503.   MOV DS,INTSEG     ;!
  504.   INT 021
  505.   MOV AX,CS
  506.   MOV DS,AX
  507.  
  508.   CALL DELAY
  509.   MOV DX,MODEM_CONTROL
  510.   IN AL,DX
  511.   AND AL,11111110xB    ;TURN DTR OFF
  512.   OUT DX,AL
  513.   CALL DELAY
  514.   MOV DX,MODEM_CONTROL
  515.   IN AL,DX
  516.   OR AL,1        ;TURN DTR BACK ON
  517.   OUT DX,AL
  518. EXIT:
  519.   MOV AH,03E        ;FUNCTION TO CLOSE FILE
  520.   MOV BX,HANDLE
  521.   INT 021
  522.   CALL CLRSCRN
  523.   MOV AX,04C00        ;EXIT TO DOS
  524.   INT 021
  525.  
  526. ;*****SUBROUTINES*****
  527.  
  528. TRANSMIT:
  529.   MOV AH,1        ;FUNCTION TO GET KEYBOARD STATUS
  530.   INT 016
  531.   JNZ PREXIT        ;IF ANY KEY PRESSED
  532. ;PUT STRING POINTED TO BY SI IN OUTPUT BUFFER
  533. LOAD_STRING:
  534.   LODSB
  535. LSLOOP:
  536.   CALL PUT_BUFF_DATA
  537.   LODSB
  538.   CMP AL,0
  539.   JNZ LSLOOP        ;IF NOT AT END OF STRING
  540.   RET
  541.  
  542. WAITFOR:
  543.   MOV DX,OFFSET BUF
  544. WAITLP:
  545.   MOV AH,1        ;FUNCTION TO GET KEYBOARD STATUS
  546.   INT 016
  547.   JNZ PREXIT        ;IF KEYBOARD INPUT
  548.   MOV DI,DX
  549.   PUSH BX
  550.   CALL GET_BUFF_DATA2    ;GET INPUT CHAR IN AL
  551.   POP BX
  552.   JNC WAITLP        ;IF NO CHAR IN BUFFER YET
  553.   AND AL,07F        ;STRIP HI BIT
  554.   STOSB         ;ADD IT TO STRING IN BUF
  555.   PUSH BX
  556.   CALL WRITE        ;WRITE CHAR ON SCREEN
  557.   POP BX
  558.   MOV SI,BX        ;OFFSET OF STRING TO MATCH
  559.   MOV CX,W[SI-2]    ;LENGTH OF STRING
  560.   MOV DX,DI        ;SAVE IT
  561.   SUB DI,CX        ;START AT BEGINNING OF POSSIBLE MATCH
  562.   REPE CMPSB
  563.   JNE WAITLP        ;IF STRING NOT RECEIVED YET
  564.   RET
  565.  
  566. WAITFOR2:
  567.   MOV DX,OFFSET BUF
  568. WAITLP2:
  569.   MOV AH,1        ;FUNCTION TO GET KEYBOARD STATUS
  570.   INT 016
  571.   JNZ PREXIT        ;IF KEYBOARD INPUT
  572.   MOV DI,DX
  573.   PUSH BX
  574.   CALL GET_BUFF_DATA2    ;GET INPUT CHAR IN AL
  575.   POP BX
  576.   JNC WAITLP2        ;IF NO CHAR IN BUFFER YET
  577.   AND AL,07F        ;STRIP HI BIT
  578.   STOSB         ;ADD IT TO STRING IN BUF
  579.   MOV SI,BX        ;OFFSET OF STRING TO MATCH
  580.   MOV CX,W[SI-2]    ;LENGTH OF STRING
  581.   MOV DX,DI        ;SAVE IT
  582.   SUB DI,CX        ;START AT BEGINNING OF POSSIBLE MATCH
  583.   REPE CMPSB
  584.   JNE WAITLP2        ;IF STRING NOT RECEIVED YET
  585.   RET
  586.  
  587. PREXIT:
  588.   POP CX        ;RET ADDRESS
  589.   MOV AH,0        ;FUNCTION TO GET KEYBOARD INPUT
  590.   INT 016
  591.   MOV DI,BUF
  592.   JMP GOMANUAL
  593.  
  594. ;WRITE TO SCREEN
  595. WRITE:
  596.   CMP AL,7
  597.   JA NOTBEEP
  598.   JB GORET        ;DON'T DISPLAY EVERYTHING
  599.   MOV AH,0E        ;WRITE BEEP
  600.   INT 010
  601. GORET:
  602.   RET
  603. NOTBEEP:
  604.   CMP AL,0D
  605.   JNE NOTCR
  606.   MOV COL,0
  607.   JMP MOVCUR
  608. NOTCR:
  609.   CMP AL,0A
  610.   JNE NOTLF
  611.   CMP ROW,24
  612.   JE ATBOT2
  613.   INC ROW
  614.   JMP MOVCUR
  615. ATBOT2:
  616.   MOV CX,AX        ;SAVE IT
  617.   MOV AL,' '
  618.   MOV AH,ATTRIB
  619.   MOV ES,SCREENSEG
  620.   MOV DS,SCREENSEG    ;!
  621.   PUSH DI
  622.   MOV SI,160
  623.   SUB DI,DI
  624.   MOV BX,24        ;ROWS TO MOVE UP
  625. SCROLL:
  626.   MOV CX,80
  627.   REP MOVSW
  628.   DEC BX
  629.   JNZ SCROLL
  630.   MOV CX,80
  631.   REP STOSW
  632.   POP DI
  633.   MOV AX,CS
  634.   MOV DS,AX
  635.   MOV ES,AX
  636.   RET
  637. NOTLF:
  638.   CMP AL,8        ;BACKSPACE
  639.   JNE NOTBS
  640.   SUB COL,2        ;SLIGHTLY TRICK
  641.   MOV AL,' '
  642.   MOV DX,ROWCOL
  643.   INC DL        ;ROW
  644.   JMP SHORT >L1
  645. NOTBS:
  646.   CMP AL,12        ;FORM FEED
  647.   JE CLRSCRN
  648. ;  CMP AL,' '
  649. ;  JB GORET         ;DON'T WRITE EVERYTHING
  650.   MOV DX,ROWCOL
  651. L1:
  652.   MOV CX,AX        ;SAVE IT
  653.   MOV ES,SCREENSEG
  654.   MOV AX,160
  655.   MUL DH        ;ROW
  656.   PUSH DI
  657.   MOV DI,AX
  658.   MOV AL,DL        ;COL
  659.   CBW
  660.   SHL AX,1
  661.   ADD DI,AX        ;SCREEN OFFSET
  662.   MOV AX,CX        ;GET IT BACK
  663.   MOV AH,ATTRIB
  664.   STOSW         ;PUT CHAR ON SCREEN
  665.   POP DI
  666.   MOV AX,DS
  667.   MOV ES,AX
  668.   INC COL
  669.   JMP MOVCUR        ;INSTEAD OF CALL MOVCUR & RET
  670.  
  671. CLRSCRN:
  672.   MOV AH,ATTRIB
  673.   MOV AL,' '
  674.   MOV ES,SCREENSEG
  675.   PUSH DI
  676.   SUB DI,DI
  677.   MOV CX,2000
  678.   REP STOSW
  679.   POP DI
  680.   MOV AX,DS
  681.   MOV ES,AX
  682.   MOV DI,BUF        ;RE-INITIALIZE
  683.   MOV W[ROWCOL],0
  684.  
  685. MOVCUR:
  686.   MOV AH,2        ;FUNCTION TO MOVE CURSOR
  687.   MOV BH,0        ;PAGE
  688.   MOV DX,ROWCOL
  689.   INT 010
  690.   RET
  691.  
  692. ;COMMUNICATIONS INTERRUPT HANDLER
  693. INT_COMM:
  694.   STI
  695.   PUSH DS,AX,BX,DX
  696.   MOV AX,CS
  697.   MOV DS,AX
  698.   MOV DX,INT_IDENT
  699.   IN AL,DX
  700. L1:
  701.   CMP AL,2
  702.   JE >L3        ;IF TRANSMIT BUFFER EMPTY
  703. ;received data, get it and store in buffer
  704.   DEC DX        ;TO PORT BASE ADDRESS
  705.   DEC DX
  706.   IN AL,DX        ;GET DATA FROM RECEIVE REGISTER
  707.   MOV BX,IN_BUFF_TAIL
  708.   MOV [BX],AL
  709.   INC BX
  710.   CMP BX,IN_BUFF_END
  711.   JNE >L2
  712.   MOV BX,IN_BUFF_BEGIN
  713. L2:
  714.   CMP BX,IN_BUFF_HEAD
  715.   JE >L7        ;IF BUFFER FULL
  716.   MOV IN_BUFF_TAIL,BX
  717.   JMP SHORT >L7
  718. ;transmit buffer empty, send a byte
  719. L3:
  720.   DEC DX        ;TO PORT BASE ADDRESS
  721.   DEC DX
  722.   MOV BX,OUT_BUFF_HEAD
  723.   CMP BX,OUT_BUFF_TAIL
  724.   JE >L6        ;IF NO DATA IN BUFFER
  725.   MOV AL,[BX]
  726.   OUT DX,AL
  727.   INC BX
  728.   CMP BX,OUT_BUFF_END
  729.   JNE >L5        ;IF NOT BEYOND END OF BUFFER AREA
  730.   MOV BX,OUT_BUFF_BEGIN
  731. L5:
  732.   MOV OUT_BUFF_HEAD,BX
  733.   JMP SHORT >L7
  734. L6:
  735.   MOV B[COMM_INT_STA],0 ;RESET TRANSMITTING DATA FLAG
  736. L7:
  737.   INC DX        ;POINT TO INT. ID REG.
  738.   INC DX
  739.   IN AL,DX
  740.   TEST AL,1
  741.   JZ L1         ;IF REQUEST PENDING
  742.   MOV AL,020        ;END OF INTERRUPT
  743.   OUT 020,AL
  744.   POP DX,BX,AX,DS
  745.   IRET
  746.  
  747. GET_BUFF_DATA:
  748.   MOV SI,OFFSET IN_BUFF_HEAD
  749.   CLI            ;Don't allow interrupts
  750.   MOV BX,[SI]
  751.   CMP BX,[SI+2]     ;Test for data in buffer
  752.   JE >L1        ;If the same, no data so exit, carry is already reset
  753.   MOV AL,[BX]        ;Get the data
  754.   INC BX        ;Point to data in buffer
  755.   CMP BX,[SI+6]     ;Beyond end of buffer area?
  756.   IF E MOV BX,[SI+4]    ;Yes, reset to buffer begin
  757.   MOV [SI],BX        ;Save new head pointer
  758.   STC            ;Indicate data is in AL
  759. L1:
  760.   STI            ;Enable interrupts
  761.   JNC GET_BUFF_DATA
  762.   RET
  763.  
  764. GET_BUFF_DATA2:
  765.   MOV SI,OFFSET IN_BUFF_HEAD
  766.   CLI            ;Don't allow interrupts
  767.   MOV BX,[SI]
  768.   CMP BX,[SI+2]     ;Test for data in buffer
  769.   JE >L1        ;If the same, no data so exit, carry is already reset
  770.   MOV AL,[BX]        ;Get the data
  771.   INC BX        ;Point to data in buffer
  772.   CMP BX,[SI+6]     ;Beyond end of buffer area?
  773.   IF E MOV BX,[SI+4]    ;Yes, reset to buffer begin
  774.   MOV [SI],BX        ;Save new head pointer
  775.   STC            ;Indicate data is in AL
  776. L1:
  777.   STI            ;Enable interrupts
  778.   RET
  779.  
  780. PUT_BUFF_DATA:
  781.   PUSH SI,DI
  782.   MOV SI,OFFSET OUT_BUFF_HEAD    ;Point to output buffer
  783.   CLI            ;Don't allow interrupts
  784.   MOV BX,[SI+2]     ;BUFFER TAIL POINTER
  785.   MOV DI,BX
  786.   INC BX        ;TO MOVE BUFFER TAIL POINTER
  787.   CMP BX,[SI+6]
  788.   IF E MOV BX,[SI+4]    ;IF AT END OF BUFFER, PUT AT BEGINNING OF BUFFER
  789.   CMP BX,[SI]
  790.   JE >L1        ;IF POTENTIAL BUFFER TAIL LOC = BUFFER HEAD LOC
  791.   MOV [DI],AL        ;STORE DATA AT OLD BUFFER TAIL
  792.   MOV [SI+2],BX     ;UPDATE BUFFER TAIL POINTER
  793.   STC            ;INDICATE DATA STORED OK
  794. L1:
  795.   PUSHF         ;Save the flags
  796.   CMP B[COMM_INT_STA],1 ;Transmit int. running?
  797.   JE >L2        ;Yes, so exit
  798.   MOV B[COMM_INT_STA],1 ;Set transmitting data flag
  799.   PUSH AX
  800.   MOV BX,[SI]        ;Get the buffer head pointer
  801.   MOV AL,[BX]        ;Get the data
  802.   INC BX        ;Point to data in buffer
  803.   CMP BX,[SI+6]     ;Beyond end of buffer area?
  804.   IF E MOV BX,[SI+4]    ;Yes, reset to buffer begin
  805.   MOV [SI],BX        ;Save new head pointer
  806.   MOV DX,TR_BUFFER    ;Get port base address
  807.   OUT DX,AL        ;Send the data out the port
  808.   POP AX
  809. L2:
  810.   STI            ;Enable interrupts
  811.   POPF
  812.   POP DI,SI
  813.   JNC PUT_BUFF_DATA
  814.   RET
  815.  
  816. WRITIT:
  817.   MOV AH,0A        ;FUNCTION TO WRITE CHAR AT CURSOR
  818.   MOV BH,0        ;PAGE NUMBER
  819.   MOV CX,1        ;NUMBER OF REPETITIONS
  820.   INT 010
  821.   RET
  822.  
  823. MAKECURLINE:
  824.   MOV AL,CURATTRIB
  825. CURLINE:
  826.   MOV DI,CURLINELOC
  827.   MOV CX,40
  828. L1:
  829.   STOSB
  830.   INC DI
  831.   LOOP L1
  832.   RET
  833.  
  834. DownloadMenu:
  835.   db '╔══════════════════════════╗'
  836.   db '║   Downloading            ║'
  837.   db '║   (1,024 Bytes/Block)    ║'
  838.   db '║                          ║'
  839.   db '║   Blocks Received: 00    ║'
  840.   db '║   Elapsed Time: 00:00    ║'
  841.   db '╚══════════════════════════╝'
  842.  
  843. DownloadName db 11 dup(?)
  844. FileSize dw ?
  845. TimerCount dw ?     ;for elapsed time
  846. Blocks dw 0
  847. LastDI dw ?
  848. LastES dw ?
  849. NAKCount db 0
  850.  
  851. ;COMPUSERVE B+ PROTOCOL...
  852. ;DLE,'B',Sequence,Type,Body,ETX,Checksum
  853. ETX equ 03
  854. ENQ equ 05
  855. DLE equ 010
  856. NAK equ 015
  857. ;XOFF equ 011    ;& 091
  858. ;XON equ 013     ;& 093
  859. ;Quoted characters: 03,05,010,011,013,015,091,093
  860. TheirSeq db ?
  861. Initialize db DLE,'+','+',DLE,'0'
  862. LeadIn db DLE,'B'
  863. MySequence db '0'
  864. MyParams db '+'
  865. ;    WS  WR  BS  CM  DQ  TL  Q1  Q2  Q3   Q4  Q5  Q6  Q7  Q8  DR  UR  FI
  866.   db  1,  1,  8,  0,  3,  0, 014, 0, 0D4,  0,  0,  0, 050, 0,  0,  0,  0
  867.   db ETX
  868.  
  869. UnQuote MACRO
  870.   cmp al,DLE
  871.   jne >L9        ;if not quoted
  872.   call Get_Buff_Data
  873.   cmp al,060
  874.   jb >L8
  875.   and al,01F        ;clear bits 7,6,5
  876.   or al,080        ;set bit 7
  877.   jmp short >L9
  878. L8:
  879.   and al,01F        ;un-quote it
  880. L9:
  881.   #EM
  882.  
  883. PutInChecksum MACRO
  884.   rol ah,1
  885.   add ah,al
  886.   adc ah,0
  887.   #EM
  888.  
  889. DOWNLOAD:
  890. ;  cli
  891. ;  mov al,3         ;8 bits, no parity, 1 stop bit
  892. ;  mov dx,Line_Control
  893. ;  out dx,al
  894. ;  sti
  895.   mov MySequence,'0'    ;initialize
  896.   mov Blocks,0
  897.   mov NAKCount,0
  898. SendInit:
  899.   mov si,offset Initialize
  900.   mov cx,5
  901. L1:
  902.   lodsb
  903.   call Put_Buff_Data
  904.   loop L1
  905. GetParameters:
  906.   mov ah,0        ;initialize for Checksum
  907.   call Get_Buff_Data
  908.   cmp al,ENQ
  909.   je SendInit
  910.   cmp al,DLE
  911.   jne GetParameters
  912.   call Get_Buff_Data
  913.   cmp al,'B'
  914.   jne GetParameters
  915.   call Get_Buff_Data
  916.   mov TheirSeq,al
  917.   PutInChecksum
  918.   call Get_Buff_Data
  919.   cmp al,'+'
  920.   jne GetParameters
  921.   PutInChecksum
  922. TheirParamLP:
  923.   call Get_Buff_Data
  924.   cmp al,ETX
  925.   je >L1        ;if at end
  926.   UnQuote        ;un-quote all chars 0-01F & 080-09F
  927.   PutInChecksum
  928.   jmp short TheirParamLP
  929. L1:
  930.   PutInChecksum     ;ETX
  931.   call Get_Buff_Data
  932.   UnQuote
  933.   cmp al,ah
  934.   if ne jmp Error    ;if Checksum not right
  935.  
  936. ;clear screen & put download window on screen
  937.   call clrscrn
  938.   mov w[rowcol],01900    ;move cursor off screen
  939.   call movcur
  940.   mov es,ScreenSeg
  941.   mov al,boxattrib
  942.   mov si,offset DownloadMenu
  943.   mov dx,1330
  944.   mov bx,7
  945. L1:
  946.   mov di,dx
  947.   mov cx,28
  948. L2:
  949.   movsb
  950.   stosb
  951.   loop L2
  952.   es mov w[di],0db    ;side shadow
  953.   add dx,160
  954.   dec bx
  955.   jnz L1
  956.   mov ah,attrib
  957.   mov al,' '
  958.   es mov w[1386],ax    ;erase part of shadow
  959.   mov di,dx
  960.   add di,2
  961.   mov ax,0db        ;bottom shadow
  962.   mov cx,28
  963.   rep stosw
  964.   mov ax,ds
  965.   mov es,ax
  966. ;get initial timer count
  967.   mov cx,040
  968.   mov ds,cx        ;!
  969.   mov ax,[06c]        ;timer count
  970.   mov cx,cs
  971.   mov ds,cx
  972.   mov TimerCount,ax
  973.  
  974.   mov al,DLE        ;positive acknowledgment
  975.   call Put_Buff_Data
  976.   mov al,TheirSeq
  977.   call Put_Buff_Data
  978.  
  979.   mov cx,2        ;do following routine twice (B+ PROTOCOL...)
  980. SendMyParams:
  981.   inc MySequence
  982.   mov ah,0        ;initialize Checksum
  983.   mov si,offset LeadIn    ;DLE,'B'
  984.   lodsb
  985.   call Put_Buff_Data
  986.   lodsb
  987.   call Put_Buff_Data
  988. SendParams:
  989.   lodsb         ;Sequence,'+',MyParams,ETX
  990.   PutInChecksum
  991.   cmp al,ETX
  992.   je ItsETX
  993.   cmp al,01F        ;Checksum
  994.   jbe LowQuote
  995.   cmp al,080
  996.   jb NoQuote
  997.   cmp al,09F
  998.   ja NoQuote
  999. HiQuote:
  1000.   push ax
  1001.   mov al,DLE
  1002.   call Put_Buff_Data
  1003.   pop ax
  1004.   and al,01F
  1005.   add al,060        ;quote it
  1006.   call Put_Buff_Data
  1007.   jmp short SendParams
  1008. LowQuote:
  1009.   push ax
  1010.   mov al,DLE
  1011.   call Put_Buff_Data
  1012.   pop ax
  1013.   add al,040        ;quote it
  1014. NoQuote:
  1015.   call Put_Buff_Data
  1016.   jmp short SendParams
  1017. ItsETX:
  1018.   call Put_Buff_Data    ;ETX
  1019.   cmp ah,01F        ;Checksum
  1020.   jbe LowQuote2
  1021.   mov al,ah
  1022.   cmp al,080
  1023.   jb NoQuote2
  1024.   cmp al,09F
  1025.   ja NoQuote2
  1026. HiQuote2:
  1027.   mov al,DLE
  1028.   call Put_Buff_Data
  1029.   mov al,ah        ;Checksum
  1030.   and al,01F
  1031.   add al,060        ;quote it
  1032.   jmp short NoQuote2
  1033. LowQuote2:
  1034.   mov al,DLE
  1035.   call Put_Buff_Data
  1036.   mov al,ah        ;Checksum
  1037.   add al,040        ;quote it
  1038. NoQuote2:
  1039.   call Put_Buff_Data
  1040.  
  1041. ;get ACK
  1042.   call Get_Buff_Data
  1043.   cmp al,DLE
  1044.   if ne jmp Error
  1045.   call Get_Buff_Data
  1046.   cmp al,MySequence
  1047.   if ne jmp Error
  1048.   dec cx
  1049.   if nz jmp SendMyParams
  1050.  
  1051. ;***NOW GET DATA PACKETS***
  1052.   sub di,di        ;to hold downloaded file
  1053.   mov es,NextSeg
  1054. GetPacket:
  1055.   mov LastDI,di     ;save it for SendNAK
  1056.   mov LastES,es     ;ditto
  1057.   call Get_Buff_Data    ;DLE
  1058.   cmp al,ENQ
  1059.   je jmpError
  1060.   cmp al,NAK
  1061.   je jmpError
  1062.   cmp al,DLE
  1063.   jne jmpError
  1064.   call Get_Buff_Data    ;'B'
  1065.   cmp al,';'
  1066.   je GetPacket        ;if Wait
  1067.   cmp al,'B'
  1068.   jne GetPacket
  1069.   call Get_Buff_Data    ;Sequence
  1070.   mov TheirSeq,al
  1071.   mov ah,al        ;initialize Checksum
  1072.   call Get_Buff_Data    ;Type
  1073.   PutInChecksum
  1074.   cmp al,'N'
  1075.   je DataLoop
  1076.   cmp al,'T'
  1077.   if e jmp GotT
  1078.   cmp al,'F'
  1079.   jne jmpError
  1080.   jmp GotF
  1081. jmpError:
  1082.   jmp Error
  1083.  
  1084. DataLoop:        ;THE BIG LOOP!!!
  1085.   call Get_Buff_Data
  1086.   cmp al,ETX
  1087.   je GotETX        ;if end of packet
  1088.   cmp al,DLE
  1089.   je IfQuoted
  1090.   rol ah,1        
  1091.   add ah,al        ;put in Checksum
  1092.   adc ah,0
  1093.   stosb         ;save data in buf
  1094.   or di,di
  1095.   jnz DataLoop
  1096.   mov cx,es
  1097.   add cx,01000
  1098.   mov es,cx
  1099.   jmp short DataLoop
  1100. IfQuoted:
  1101.   call Get_Buff_Data
  1102.   cmp al,060
  1103.   jb >L1
  1104.   and al,01F        ;clear bits 7,6,5
  1105.   or al,080        ;set bit 7
  1106.   rol ah,1
  1107.   add ah,al
  1108.   adc ah,0
  1109.   stosb         ;save data in buf
  1110.   or di,di
  1111.   jnz DataLoop
  1112.   mov cx,es
  1113.   add cx,01000
  1114.   mov es,cx
  1115.   jmp short DataLoop
  1116. L1:
  1117.   and al,01F        ;un-quote it
  1118.   rol ah,1
  1119.   add ah,al
  1120.   adc ah,0
  1121.   stosb         ;save data in buf
  1122.   or di,di
  1123.   jnz DataLoop
  1124.   mov cx,es
  1125.   add cx,01000
  1126.   mov es,cx
  1127.   jmp short DataLoop
  1128. GotETX:
  1129.   PutInChecksum     ;ETX
  1130.   call Get_Buff_Data    ;Checksum
  1131.   UnQuote
  1132. ;show elapsed time
  1133. ElapsedTime:
  1134.   push es
  1135.   mov es,ScreenSeg
  1136.   push ax
  1137.   mov ax,040
  1138.   mov ds,ax        ;!
  1139.   mov ax,w[06c]     ;timer count
  1140.   mov cx,cs
  1141.   mov ds,cx
  1142.   sub ax,TimerCount
  1143.   sub dx,dx
  1144.   mov cx,10
  1145.   mul cx
  1146.   mov cx,182
  1147.   div cx        ;div 18.2
  1148.   sub dx,dx
  1149.   mov cx,60
  1150.   div cx        ;minutes in ax & seconds in dx
  1151.   aam
  1152.   add ax,03030
  1153.   es mov b[2166],ah
  1154.   es mov b[2168],al
  1155.   mov ax,dx
  1156.   aam
  1157.   add ax,03030
  1158.   es mov b[2172],ah
  1159.   es mov b[2174],al
  1160. NoCount:
  1161.   pop ax
  1162.   cmp al,ah
  1163.   je ShowBlocks     ;if Checksum is okay
  1164.   pop es
  1165.   jmp SendNAK
  1166. ;show blocks received
  1167. ShowBlocks:
  1168.   push di
  1169.   inc Blocks
  1170.   mov ax,Blocks
  1171.   mov di,2012
  1172.   sub dx,dx
  1173.   div w[Hundred]
  1174.   or ax,ax
  1175.   jz >L1
  1176.   add al,'0'
  1177.   es mov b[di],al
  1178.   add di,2
  1179. L1:
  1180.   mov ax,dx        ;remainder
  1181.   aam
  1182.   or ax,03030
  1183.   xchg al,ah
  1184.   stosb
  1185.   inc di
  1186.   mov al,ah
  1187.   stosb
  1188.   pop di,es
  1189. ;send ACK
  1190.   mov al,DLE
  1191.   call Put_Buff_Data
  1192.   mov al,TheirSeq
  1193.   call Put_Buff_Data
  1194.   jmp GetPacket
  1195.  
  1196. SendNAK:
  1197.   mov ax,0e07
  1198.   int 010
  1199.   inc NAKCount
  1200.   cmp NAKCount,5
  1201.   if e jmp Error
  1202.   mov al,NAK
  1203.   call Put_Buff_Data
  1204.   call Get_Buff_Data    ;ENQ
  1205.   call Get_Buff_Data    ;ENQ
  1206.   mov al,DLE
  1207.   call Put_Buff_Data    ;Positive ACK
  1208.   mov al,TheirSeq
  1209.   call Put_Buff_Data
  1210.   mov al,DLE
  1211.   call Put_Buff_Data
  1212.   mov al,TheirSeq
  1213.   call Put_Buff_Data
  1214.   mov di,LastDI
  1215.   jmp GetPacket
  1216.  
  1217. GotT:
  1218.   call Get_Buff_Data
  1219.   cmp al,'D'            ;download
  1220.   je DownloadType
  1221.   cmp al,'C'            ;close (end of download)
  1222.   if ne jmp Error
  1223.   mov ax,0e07        ;beep
  1224.   int 010
  1225. L1:
  1226.   call Get_Buff_Data
  1227.   cmp al,ENQ
  1228.   if e jmp DLExit
  1229.   cmp al,ETX
  1230.   jne L1        ;we only care about the 'C'
  1231.   call Get_Buff_Data    ;Checksum
  1232.   cmp al,DLE
  1233.   if ne jmp DLExit
  1234.   call Get_Buff_Data
  1235.   jmp DLExit
  1236. DownloadType:
  1237.   PutInChecksum
  1238.   call Get_Buff_Data
  1239.   PutInChecksum
  1240.   cmp al,'B'
  1241.   jne Error        ;should be a binary file
  1242.   push di,es
  1243.   mov cx,ds
  1244.   mov es,cx
  1245.   mov di,offset DownloadName
  1246. GetName:
  1247.   call Get_Buff_Data
  1248.   cmp al,ETX
  1249.   je GotName
  1250.   PutInChecksum
  1251.   stosb
  1252.   jmp short GetName
  1253.  
  1254. GotName:
  1255.   mov es,ScreenSeg
  1256.   mov di,1522
  1257.   mov si,offset DownloadName
  1258.   mov cx,10
  1259. L1:
  1260.   movsb
  1261.   inc di
  1262.   loop L1
  1263.   pop es,di
  1264.   PutInChecksum     ;ETX
  1265.   call Get_Buff_Data    ;Checksum
  1266.   UnQuote
  1267.   cmp al,ah
  1268.   if ne jmp SendNAK    ;if Checksum not right
  1269. ;send ACK
  1270.   mov al,DLE
  1271.   call Put_Buff_Data
  1272.   mov al,TheirSeq
  1273.   call Put_Buff_Data
  1274.   jmp GetPacket
  1275.  
  1276. GotF:
  1277. Error:
  1278.   mov ax,0e07        ;beep
  1279.   int 010
  1280.   mov si,offset Initialize
  1281.   mov cx,2
  1282. L1:
  1283.   lodsb
  1284.   call Put_Buff_Data
  1285.   loop L1
  1286.   call Get_Buff_Data    ;ENQ
  1287.   mov si,offset Initialize
  1288.   mov cx,5
  1289. L2:
  1290.   lodsb
  1291.   call Put_Buff_Data
  1292.   loop L2
  1293.   jmp short DLExit2
  1294.  
  1295. DLExit:
  1296.   mov al,DLE
  1297.   call Put_Buff_Data
  1298.   mov al,TheirSeq
  1299.   call Put_Buff_Data
  1300.  
  1301. ;save data in file
  1302.   mov FileSize,di
  1303.   mov ah,03C        ;function to create/truncate file
  1304.   sub cx,cx        ;file attrib
  1305.   mov dx,offset DownloadName
  1306.   int 021
  1307.   mov bx,ax        ;handle
  1308.   mov dx,NextSeg    ;first segment
  1309.   mov bp,es
  1310.   sub bp,dx
  1311.   mov cl,4
  1312.   rol bp,cl        ;number of segments
  1313.   mov ax,FileSize    ;size of last segment
  1314. Writelp2:
  1315.   mov TempStorage,ax
  1316.   mov cx,0FFF0
  1317.   or bp,bp
  1318.   if z mov cx,ax
  1319.   mov ds,dx        ;!
  1320.   push dx
  1321.   sub dx,dx
  1322.   mov ah,040        ;function to write file
  1323.   int 021
  1324.   mov dx,cs
  1325.   mov ds,dx
  1326.   pop dx
  1327.   add dx,0FFF
  1328.   jc Writexit        ;if more than 1 meg
  1329.   or ax,ax
  1330.   jz Writexit        ;if disk full
  1331.   mov ax,TempStorage
  1332.   sub ax,0FFF0
  1333.   sbb bp,0
  1334.   jns Writelp2
  1335. Writexit:
  1336.   mov ah,03E        ;function to close file
  1337.   int 021
  1338. DLExit2:
  1339. ;  cli
  1340. ;  mov al,00011010xB     ;7 bits, even parity, 1 stop bit
  1341. ;  mov dx,Line_Control
  1342. ;  out dx,al
  1343. ;  sti
  1344.   mov w[rowcol],01000    ;row 16
  1345.   call movcur
  1346. L1:
  1347.   mov ah,1
  1348.   int 016
  1349.   jz >L2        ;if no key pressed
  1350.   mov ah,0
  1351.   int 016        ;get rid of any keyboard input
  1352.   jmp short L1
  1353. L2:
  1354.   jmp DownloadRet
  1355.  
  1356. ;DELAY, USING INT 015 EVENT WAIT, OR LOOP
  1357. DELAY:
  1358.   MOV BX,OFFSET FLAGBYTE
  1359.   MOV B[BX],0
  1360.   MOV CX,8        ;HIGH COUNT
  1361.   SUB DX,DX        ;LOW COUNT
  1362.   MOV AX,08300
  1363.   INT 015
  1364.   JC >L1        ;IF FUNCTION DOESN'T WORK ON THIS COMPUTER
  1365. L0:
  1366.   TEST B[BX],080
  1367.   JZ L0         ;LOOP UNTIL HIGH BIT IS SET
  1368.   RET
  1369. L1:
  1370.   MOV CX,0FFFF
  1371. L2:
  1372.   MOV BX,8
  1373. L3:
  1374.   DEC BX
  1375.   JNZ L3
  1376.   LOOP L2
  1377.   RET
  1378.  
  1379. ;MOVE CONFIG DATA FROM BUF TO PHONE2, SENDUSER, & SENDPASS
  1380. BUF2MEM:
  1381.   MOV BX,OFFSET BUF
  1382.   MOV SI,BX
  1383.   MOV DI,OFFSET PHONE2
  1384.   MOV CX,22
  1385. L1:
  1386.   LODSB
  1387.   CMP AL,' '
  1388.   JE >L3        ;AT END OF NUMBER
  1389.   CMP AL,'-'
  1390.   JE >L2
  1391.   CMP AL,'('
  1392.   JE >L2
  1393.   CMP AL,')'
  1394.   JE >L2
  1395.   STOSB
  1396. L2:
  1397.   LOOP L1
  1398. L3:
  1399.   MOV W[DI],0D        ;0D,0
  1400.   ADD BX,22
  1401.   MOV SI,BX
  1402.   MOV DI,OFFSET SENDUSER
  1403.   MOV CX,22
  1404. L4:
  1405.   LODSB
  1406.   CMP AL,' '
  1407.   JE >L5
  1408.   STOSB
  1409.   LOOP L4
  1410. L5:
  1411.   MOV W[DI],0D
  1412.   ADD BX,22
  1413.   MOV SI,BX
  1414.   MOV DI,OFFSET SENDPASS
  1415.   MOV CX,22
  1416. L6:
  1417.   LODSB
  1418.   CMP AL,' '
  1419.   JE >L7
  1420.   STOSB
  1421.   LOOP L6
  1422. L7:
  1423.   MOV W[DI],0D
  1424.   ADD BX,22
  1425.   MOV SI,BX
  1426.   MOV DI,OFFSET SPEED
  1427.   MOV CX,4
  1428.   REP MOVSB
  1429.   ADD BX,22
  1430.   MOV SI,BX
  1431.   MOV DI,OFFSET COMPORT
  1432.   MOVSB
  1433.   RET
  1434.  
  1435. COMMENT @
  1436. ;FOLLOWING IS A TEMPLATE FOR USING CRC INSTEAD OF CHECKSUM
  1437. CRC_TABLE:
  1438.   DW    00000, 01021, 02042, 03063, 04084, 050A5, 060C6, 070E7
  1439.   DW    08108, 09129, 0A14A, 0B16B, 0C18C, 0D1AD, 0E1CE, 0F1EF
  1440.   DW    01231, 00210, 03273, 02252, 052B5, 04294, 072F7, 062D6
  1441.   DW    09339, 08318, 0B37B, 0A35A, 0D3BD, 0C39C, 0F3FF, 0E3DE
  1442.   DW    02462, 03443, 00420, 01401, 064E6, 074C7, 044A4, 05485
  1443.   DW    0A56A, 0B54B, 08528, 09509, 0E5EE, 0F5CF, 0C5AC, 0D58D
  1444.   DW    03653, 02672, 01611, 00630, 076D7, 066F6, 05695, 046B4
  1445.   DW    0B75B, 0A77A, 09719, 08738, 0F7DF, 0E7FE, 0D79D, 0C7BC
  1446.   DW    048C4, 058E5, 06886, 078A7, 00840, 01861, 02802, 03823
  1447.   DW    0C9CC, 0D9ED, 0E98E, 0F9AF, 08948, 09969, 0A90A, 0B92B
  1448.   DW    05AF5, 04AD4, 07AB7, 06A96, 01A71, 00A50, 03A33, 02A12
  1449.   DW    0DBFD, 0CBDC, 0FBBF, 0EB9E, 09B79, 08B58, 0BB3B, 0AB1A
  1450.   DW    06CA6, 07C87, 04CE4, 05CC5, 02C22, 03C03, 00C60, 01C41
  1451.   DW    0EDAE, 0FD8F, 0CDEC, 0DDCD, 0AD2A, 0BD0B, 08D68, 09D49
  1452.   DW    07E97, 06EB6, 05ED5, 04EF4, 03E13, 02E32, 01E51, 00E70
  1453.   DW    0FF9F, 0EFBE, 0DFDD, 0CFFC, 0BF1B, 0AF3A, 09F59, 08F78
  1454.   DW    09188, 081A9, 0B1CA, 0A1EB, 0D10C, 0C12D, 0F14E, 0E16F
  1455.   DW    01080, 000A1, 030C2, 020E3, 05004, 04025, 07046, 06067
  1456.   DW    083B9, 09398, 0A3FB, 0B3DA, 0C33D, 0D31C, 0E37F, 0F35E
  1457.   DW    002B1, 01290, 022F3, 032D2, 04235, 05214, 06277, 07256
  1458.   DW    0B5EA, 0A5CB, 095A8, 08589, 0F56E, 0E54F, 0D52C, 0C50D
  1459.   DW    034E2, 024C3, 014A0, 00481, 07466, 06447, 05424, 04405
  1460.   DW    0A7DB, 0B7FA, 08799, 097B8, 0E75F, 0F77E, 0C71D, 0D73C
  1461.   DW    026D3, 036F2, 00691, 016B0, 06657, 07676, 04615, 05634
  1462.   DW    0D94C, 0C96D, 0F90E, 0E92F, 099C8, 089E9, 0B98A, 0A9AB
  1463.   DW    05844, 04865, 07806, 06827, 018C0, 008E1, 03882, 028A3
  1464.   DW    0CB7D, 0DB5C, 0EB3F, 0FB1E, 08BF9, 09BD8, 0ABBB, 0BB9A
  1465.   DW    04A75, 05A54, 06A37, 07A16, 00AF1, 01AD0, 02AB3, 03A92
  1466.   DW    0FD2E, 0ED0F, 0DD6C, 0CD4D, 0BDAA, 0AD8B, 09DE8, 08DC9
  1467.   DW    07C26, 06C07, 05C64, 04C45, 03CA2, 02C83, 01CE0, 00CC1
  1468.   DW    0EF1F, 0FF3E, 0CF5D, 0DF7C, 0AF9B, 0BFBA, 08FD9, 09FF8
  1469.   DW    06E17, 07E36, 04E55, 05E74, 02E93, 03EB2, 00ED1, 01EF0
  1470.  
  1471. CRC DW 0FFFF    ;01500
  1472. VALUE DB '3','T','D','B','PISLCC.L15',3 ;DLE,055,DLE,040
  1473.  
  1474. ;crc = table [((crc shr 8) xor (value)) and $ff] xor (crc shl 8)
  1475. GETCRC:
  1476.   MOV AX,CRC
  1477.   MOV SI,OFFSET VALUE
  1478.   MOV CX,15
  1479. L1:
  1480.   MOV DX,AX
  1481.   MOV AL,AH
  1482.   MOV AH,0
  1483.   MOV DH,DL
  1484.   MOV DL,AH
  1485.   XOR AL,[SI]
  1486.   INC SI
  1487.   MOV BX,AX
  1488.   SHL BX,1
  1489.   MOV AX,CRC_TABLE[BX]
  1490.   XOR AX,DX
  1491.   LOOP L1
  1492.   MOV CRC,AX
  1493.   RET
  1494. @
  1495.  
  1496. IN_BUFF EQU $
  1497. IN_BUFF_SIZE EQU 04000
  1498. OUT_BUFF_SIZE EQU 04000
  1499. OUT_BUFF EQU IN_BUFF + IN_BUFF_SIZE
  1500. BUF EQU OUT_BUFF + OUT_BUFF_SIZE
  1501.  
  1502.